#include <QCheckBox>
#include <QDebug>
#include <QFrame>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QListWidget>
#include <QMessageBox>
#include <QPoint>
#include <QScrollBar>
#include <QToolButton>

#include "cxicombobox_p.h"
#include "cxicomboboxbase.h"
#include "cxipopupbox.h"
#include "cxitagwidget.h"
#include <controls/combobox/cximuticombobox.h>
CxiMutiComboBoxPrivate::CxiMutiComboBoxPrivate(CxiMutiComboBox* p)
	: q_ptr(p), m_comboBoxBase(nullptr), m_selectAll(nullptr),
	  m_line(nullptr), m_popup(nullptr), m_listWidget(nullptr),
	  m_topLayout(nullptr), m_count(0), m_totalMatched(0), m_popupBox(nullptr),
	  m_tagWidgets(nullptr), m_existingTags(nullptr),
	  m_visibleCount(0), m_batchSize(200), m_loading(false)
{
	init();
	initConnect();
}

CxiMutiComboBoxPrivate::~CxiMutiComboBoxPrivate() = default;

void CxiMutiComboBoxPrivate::init()
{
	Q_Q(CxiMutiComboBox);

	m_mainLayout = new QVBoxLayout(q);
	m_mainLayout->setContentsMargins(5, 5, 5, 5);
	m_mainLayout->setSpacing(5);

	m_comboBoxBase = new CxiComboBoxBase(q);
	m_popupBox = new CxiPopupBox(q);

	m_comboBoxBase->setLineMinWidth(q->width() * 0.25);
	m_comboBoxBase->setBtnText("▼");
	m_comboBoxBase->setBtnSize(24, 24);

	m_topLayout = new QHBoxLayout();
	m_topLayout->addWidget(m_comboBoxBase);
	m_mainLayout->addLayout(m_topLayout);

	q->setLayout(m_mainLayout);

	m_popup = new QFrame(q, Qt::Popup);
	m_popup->setFrameShape(QFrame::StyledPanel);
	m_popup->setMinimumHeight(180);
	m_popup->setMinimumWidth(250);

	m_popupLayout = new QVBoxLayout(m_popup);
	m_popupLayout->setContentsMargins(5, 5, 5, 5);
	m_popupLayout->setSpacing(5);

	m_selectAll = new QCheckBox("全选", m_popup);
	m_popupLayout->addWidget(m_selectAll);

	m_line = new QFrame(m_popup);
	m_popupLayout->addWidget(m_line);

	m_selectAll->hide();
	m_line->hide();

	m_listWidget = new QListWidget(m_popup);
	m_popupLayout->addWidget(m_listWidget);

	m_popup->hide();

	m_tagWidgets = new QVector<CxiTagWidget*>;
	m_existingTags = new QSet<QString>;
}

void CxiMutiComboBoxPrivate::initConnect()
{
	Q_Q(CxiMutiComboBox);
	// 下拉框 弹出信号槽
	connect(m_comboBoxBase, &CxiComboBoxBase::showPopup, this, [this, q]() {
		showPopup();
	});

	// 按下回车触发搜索 信号槽
	connect(m_comboBoxBase, &CxiComboBoxBase::textEditFinished, this, [this]() {
		searchItems();
	});

	// 列表项点击信号槽
	connect(m_listWidget, &QListWidget::itemClicked, this, [this](QListWidgetItem* item) {
		if (item->checkState() == Qt::Checked)
		{
			item->setCheckState(Qt::Unchecked);
		}
		else
		{
			item->setCheckState(Qt::Checked);
		}
	});

	// 左侧复选框改变信号槽
	connect(m_listWidget, &QListWidget::itemChanged, this, [this](QListWidgetItem* item) {
		handleItemChanged(item);
	});

	// 是否显示全选复选框 信号槽
	connect(this, &CxiMutiComboBoxPrivate::visibleItemsChanged, this, [this](bool isVisiable) {
		isShowSelectAllBox(isVisiable);
	});

	// 全选复选框改变信号槽
	connect(m_selectAll, &QCheckBox::stateChanged, this, [this](int state) {
		selectAllItem(state);
	});

	// 是否显示多选框
	connect(this, &CxiMutiComboBoxPrivate::isShowPopupButton, [this](int count) {
		m_comboBoxBase->isShowPopupButton(count);
	});

	// 懒加载策略
	connect(m_listWidget->verticalScrollBar(), &QScrollBar::valueChanged,
			this, [this](int value) {
				QScrollBar* bar = m_listWidget->verticalScrollBar();
				if (!m_loading && value >= bar->maximum() - 2) {
					m_loading = true;
					showMoreItems();
					m_loading = false;
				}
			});

}

void CxiMutiComboBoxPrivate::addItem(const ComboItem& item)
{
	if (m_existingTags->contains(item.display))
		return;

	m_existingTags->insert(item.display);

	auto* listItem = new QListWidgetItem(m_listWidget);
	listItem->setFlags(listItem->flags() | Qt::ItemIsUserCheckable |
					   Qt::ItemIsSelectable | Qt::ItemIsEnabled);
	listItem->setData(Qt::DisplayRole, item.display);
	listItem->setData(Qt::UserRole, QVariant::fromValue(item));
	listItem->setData(Qt::DecorationRole, QIcon(":/icon/cmb.png"));

	if (++m_count > 200)
	{
		emit isShowPopupButton(m_count);
	}
}

void CxiMutiComboBoxPrivate::setPopupVisible(bool visible)
{
	m_listWidget->setVisible(visible);
}

void CxiMutiComboBoxPrivate::handleItemChanged(QListWidgetItem* item)
{
	Q_Q(CxiMutiComboBox);
	QString text = item->text();

	if (item->checkState() == Qt::Checked)
	{
		addTag(text);
	}
	else if (item->checkState() == Qt::Unchecked)
	{
		deleteTag(text);
	}

	updateTagLayout();
	refreshTagLayout();
}

void CxiMutiComboBoxPrivate::addTag(const QString& text)
{
	Q_Q(CxiMutiComboBox);
	auto* tagw = new CxiTagWidget(text, q);
	m_comboBoxBase->addWidget(tagw);
	m_tagWidgets->append(tagw);
	// 连接删除信号
	connect(tagw, &CxiTagWidget::tagRemoved, this, [this, text]() {
		for (int i = 0; i < m_listWidget->count(); ++i)
		{
			auto* listItem = m_listWidget->item(i);
			if (listItem->text() == text)
			{
				listItem->setCheckState(Qt::Unchecked);
				emit removeTag(text);
				break;
			}
		}
	});
}

void CxiMutiComboBoxPrivate::updateTagLayout()
{
	Q_Q(CxiMutiComboBox);

	// 最大宽度
	int maxWidth = q->width() - m_comboBoxBase->btnWidth() - m_comboBoxBase->lineMinWidth() - 20;
	// 使用宽度
	int usedWidth = 0;
	// 长度溢出标志位
	bool overflow = false;
	//  显示的标签数量 为了计算+n使用
	int visibleCount = 0;

	for (auto* tag: *m_tagWidgets)
	{
		int w = tag->sizeHint().width() + m_comboBoxBase->getWidgetSpacing();
		if (usedWidth + w > maxWidth)
		{
			tag->hide();
			overflow = true;
		}
		else
		{
			tag->show();
			usedWidth += w;
			++visibleCount;
		}
	}
	m_popupBox->clearTags();

	if (overflow)
	{
		if (!m_popupBox)
		{
			m_popupBox = new CxiPopupBox(q);
		}

		int hiddenCount = 0;
		for (auto* tag: *m_tagWidgets)
		{
			if (tag->isHidden())
			{
				auto* cloneTag = new CxiTagWidget(tag->text(), m_popupBox);
				m_popupBox->addTag(cloneTag);
				++hiddenCount;

				connect(cloneTag, &CxiTagWidget::tagRemoved, this, [this, text = tag->text()]() {
					for (int i = 0; i < m_listWidget->count(); ++i)
					{
						auto* listItem = m_listWidget->item(i);
						if (listItem->text() == text)
						{
							listItem->setCheckState(Qt::Unchecked);
							emit removeTag(text);
							break;
						}
					}
				});
			}
		}

		m_popupBox->setCount(hiddenCount);
		m_comboBoxBase->resetPopupBox(m_popupBox);
		m_popupBox->show();
		m_popupBox->show();
	}
	else if (m_popupBox)
	{
		m_popupBox->hide();
	}
}

void CxiMutiComboBoxPrivate::refreshTagLayout()
{
	Q_Q(CxiMutiComboBox);
	if (m_tagWidgets->isEmpty())
	{
		m_comboBoxBase->setWidgetFixedWidth(0);
	}
	else
	{
		m_comboBoxBase->setTagWidgetLayoutPolicy();
	}

	m_comboBoxBase->refreshTagLayout();
	q->updateGeometry();
}

void CxiMutiComboBoxPrivate::deleteTag(const QString& text)
{
	for (int i = 0; i < m_tagWidgets->size(); ++i)
	{
		auto* tagw = m_tagWidgets->at(i);
		if (tagw->text() == text)
		{
			m_comboBoxBase->removeTag(tagw);
			m_tagWidgets->removeAt(i);
			tagw->deleteLater();
			break;
		}
	}
}

void CxiMutiComboBoxPrivate::isShowSelectAllBox(bool isVisiable)
{
	if (!isVisiable)
	{
		m_selectAll->hide();
		m_line->hide();
	}
	else
	{
		m_selectAll->show();
		m_line->show();
	}
}

void CxiMutiComboBoxPrivate::selectAllItem(int state)
{
	m_listWidget->blockSignals(true);

	for (int i = 0; i < m_listWidget->count(); ++i)
	{
		auto* item = m_listWidget->item(i);
		if (!item->isHidden())
		{
			item->setCheckState(state ? Qt::Checked : Qt::Unchecked);
		}
	}

	m_listWidget->blockSignals(false);

	// 全选或全不选后手动同步一次 UI
	if (state == Qt::Checked)
	{
		for (int i = 0; i < m_listWidget->count(); ++i)
		{
			auto* item = m_listWidget->item(i);
			if (!item->isHidden() && item->checkState() == Qt::Checked)
			{
				addTag(item->text());
			}
		}
	}
	else
	{
		for (auto* tag: *m_tagWidgets)
		{
			tag->deleteLater();
		}
		m_tagWidgets->clear();
	}

	updateTagLayout();
	refreshTagLayout();
}

void CxiMutiComboBoxPrivate::searchItems()
{
	QString keyword = m_comboBoxBase->lineEditText().trimmed();


	m_listWidget->setUpdatesEnabled(false);

	// 统计显示的数量，并先把所有匹配项先隐藏（统一由下面的逻辑决定哪些显示）
	int matchedTotal = 0;
	for (int i = 0; i < m_listWidget->count(); ++i)
	{
		auto* item = m_listWidget->item(i);
		auto combo = item->data(Qt::UserRole).value<ComboItem>();
		bool matched = combo.hasSubString(keyword);
		// 先把匹配项隐藏（默认隐藏），未匹配的也隐藏（保持一致）
		item->setHidden(true);

		if (matched)
		{
			++matchedTotal;
		}
	}

	// 决定本次要展示多少（最多 m_batchSize）
	m_visibleCount = qMin(m_batchSize, matchedTotal);
	m_loading = false;

	// 将前 m_visibleCount 个匹配项设为可见
	int shown = 0;
	int matchedIndex = 0;
	for (int i = 0; i < m_listWidget->count() && shown < m_visibleCount; ++i)
	{
		auto* item = m_listWidget->item(i);
		auto combo = item->data(Qt::UserRole).value<ComboItem>();
		if (combo.hasSubString(keyword))
		{
			// 只有当 matchedIndex 在前 m_visibleCount 区间时才显示
			if (matchedIndex < m_visibleCount)
			{
				item->setHidden(false);
				++shown;
			}
			++matchedIndex;
		}
	}

	m_listWidget->setUpdatesEnabled(true);

	showPopup();
}

void CxiMutiComboBoxPrivate::showPopup()
{
	Q_Q(CxiMutiComboBox);
	if (!m_popup)
		return;

	if (m_popup->isVisible() && !m_comboBoxBase->lineEditorHasFocus())
	{
		m_popup->hide();
	}
	else
	{
		m_popup->move(q->mapToGlobal(m_topLayout->geometry().bottomLeft()));
		m_popup->resize(q->width(), 180);
		m_popup->show();
		m_popup->raise();
	}
	emit visibleItemsChanged(m_visibleCount > 0);
}
QVector<QVariant> CxiMutiComboBoxPrivate::getTags() const
{
	QVector<QVariant> res;
	for (int i = 0; i < m_listWidget->count(); ++i)
	{
		auto* item = m_listWidget->item(i);
		if (item->checkState() == Qt::Checked)
		{
			ComboItem combo = item->data(Qt::UserRole).value<ComboItem>();
			res.append(combo.tag);
		}
	}
	return res;
}

QVector<QString> CxiMutiComboBoxPrivate::getDatas() const
{
	QVector<QString> res;
	for (int i = 0; i < m_listWidget->count(); ++i)
	{
		auto* item = m_listWidget->item(i);
		if (item->checkState() == Qt::Checked)
		{
			ComboItem combo = item->data(Qt::UserRole).value<ComboItem>();
			res.append(combo.data);
		}
	}
	return res;
}
// 滚动到底部 触发的槽函数之一
void CxiMutiComboBoxPrivate::showMoreItems()
{
	QString keyword = m_comboBoxBase->lineEditText().trimmed();

	int matchedTotal = 0;
	for (int i = 0; i < m_listWidget->count(); ++i)
	{
		auto combo = m_listWidget->item(i)->data(Qt::UserRole).value<ComboItem>();
		if (combo.hasSubString(keyword))
			++matchedTotal;
	}

	if (m_visibleCount >= matchedTotal)
		return; // 全部已显示，防止脏加载

	int nextEnd = qMin(m_visibleCount + m_batchSize, matchedTotal);

	m_listWidget->setUpdatesEnabled(false);

	int shown = 0;
	int matchedIndex = 0;
	for (int i = 0; i < m_listWidget->count() && shown < (nextEnd - m_visibleCount); ++i)
	{
		QListWidgetItem* item = m_listWidget->item(i);
		auto combo = item->data(Qt::UserRole).value<ComboItem>();
		if (combo.hasSubString(keyword))
		{
			if (matchedIndex >= m_visibleCount && matchedIndex < nextEnd)
			{
				item->setHidden(false);
				++shown;
			}
			++matchedIndex;
		}
	}

	m_listWidget->setUpdatesEnabled(true);
	m_visibleCount = nextEnd;
}
